﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Xml.Serialization;

public class Order : IEquatable<Order>
{
    public int Id { get; set; }
    public string Customer { get; set; }
    public List<OrderDetail> OrderDetails { get; set; }
    public Order() 
    {
        OrderDetails = new List<OrderDetail>();
    }

    public Order(int id, string customer)
    {
        Id = id;
        Customer = customer;
        OrderDetails = new List<OrderDetail>();
    }

    public bool Equals(Order other)
    {
        if (other == null) return false;
        return Id == other.Id;
    }

    public override string ToString()
    {
        return $"Order Id: {Id}, Customer: {Customer}";
    }
}

public class OrderDetail : IEquatable<OrderDetail>
{
    public int ProductId { get; set; }
    public string ProductName { get; set; }
    public int Quantity { get; set; }
    public decimal Price { get; set; }
    public OrderDetail()  
    {
    }
    public OrderDetail(int productId, string productName, int quantity, decimal price)
    {
        ProductId = productId;
        ProductName = productName;
        Quantity = quantity;
        Price = price;
    }

    public bool Equals(OrderDetail other)
    {
        if (other == null) return false;
        return ProductId == other.ProductId;
    }

    public override string ToString()
    {
        return $"Product Id: {ProductId}, Product Name: {ProductName}, Quantity: {Quantity}, Price: {Price}";
    }
}

public class OrderService
{
    public List<Order> Orders { get; set; }

    public OrderService()
    {
        Orders = new List<Order>();
    }

    public void AddOrder(Order order)
    {
        if (Orders.Contains(order))
        {
            throw new ArgumentException("Order already exists.");
        }
        Orders.Add(order);
    }

    public void DeleteOrder(int orderId)
    {
        var order = Orders.FirstOrDefault(o => o.Id == orderId);
        if (order == null)
        {
            throw new ArgumentException("Order not found.");
        }
        Orders.Remove(order);
    }

    public void UpdateOrder(Order updatedOrder)
    {
        var order = Orders.FirstOrDefault(o => o.Id == updatedOrder.Id);
        if (order == null)
        {
            throw new ArgumentException("Order not found.");
        }
        order.Customer = updatedOrder.Customer;
        order.OrderDetails = updatedOrder.OrderDetails;
    }

    public IEnumerable<Order> QueryOrdersByOrderNumber(int orderNumber)
    {
        return Orders.Where(o => o.Id == orderNumber).OrderBy(o => o.OrderDetails.Sum(od => od.Price * od.Quantity));
    }

    public IEnumerable<Order> QueryOrdersByProductName(string productName)
    {
        return Orders.Where(o => o.OrderDetails.Any(od => od.ProductName == productName)).OrderBy(o => o.OrderDetails.Sum(od => od.Price * od.Quantity));
    }

    public IEnumerable<Order> QueryOrdersByCustomer(string customer)
    {
        return Orders.Where(o => o.Customer == customer).OrderBy(o => o.OrderDetails.Sum(od => od.Price * od.Quantity));
    }

    public IEnumerable<Order> QueryOrdersByAmount(decimal amount)
    {
        return Orders.Where(o => o.OrderDetails.Sum(od => od.Price * od.Quantity) == amount).OrderBy(o => o.OrderDetails.Sum(od => od.Price * od.Quantity));
    }

    public void SortOrders(Func<Order, object> sortFunc = null)
    {
        Orders = sortFunc == null ? Orders.OrderBy(o => o.Id).ToList() : Orders.OrderBy(sortFunc).ToList();
    }
    public void Export(string fileName)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(List<Order>));
        using (TextWriter writer = new StreamWriter(fileName))
        {
            serializer.Serialize(writer, Orders);
        }
    }

    public void Import(string fileName)
    {
        XmlSerializer serializer = new XmlSerializer(typeof(List<Order>));
        using (TextReader reader = new StreamReader(fileName))
        {
            Orders = (List<Order>)serializer.Deserialize(reader);
        }
    }
}

class Program
{
    static void Main(string[] args)
    {
        OrderService orderService = new OrderService();
        Order order1 = new Order(1, "Alice");
        order1.OrderDetails.Add(new OrderDetail(1, "Product1", 3, 10));
        order1.OrderDetails.Add(new OrderDetail(2, "Product2", 2, 15));

        Order order2 = new Order(2, "Bob");
        order2.OrderDetails.Add(new OrderDetail(1, "Product1", 1, 10));
        order2.OrderDetails.Add(new OrderDetail(3, "Product3", 5, 8));
        try
        {
            orderService.AddOrder(order1);
            orderService.AddOrder(order2);

            Console.WriteLine("Orders sorted by order number:");
            orderService.SortOrders();
            foreach (var order in orderService.Orders)
            {
                Console.WriteLine(order);
            }

            Console.WriteLine("\nOrders sorted by total amount:");
            orderService.SortOrders(o => o.OrderDetails.Sum(od => od.Price * od.Quantity));
            foreach (var order in orderService.Orders)
            {
                Console.WriteLine(order);
            }

            Console.WriteLine("\nQuery by order number (1):");
            var ordersByNumber = orderService.QueryOrdersByOrderNumber(1);
            foreach (var order in ordersByNumber)
            {
                Console.WriteLine(order);
            }

            Console.WriteLine("\nQuery by product name (Product1):");
            var ordersByProduct = orderService.QueryOrdersByProductName("Product1");
            foreach (var order in ordersByProduct)
            {
                Console.WriteLine(order);
            }

            Console.WriteLine("\nQuery by customer (Alice):");
            var ordersByCustomer = orderService.QueryOrdersByCustomer("Alice");
            foreach (var order in ordersByCustomer)
            {
                Console.WriteLine(order);
            }

            Console.WriteLine("\nQuery by amount (50):");
            var ordersByAmount = orderService.QueryOrdersByAmount(50);
            foreach (var order in ordersByAmount)
            {
                Console.WriteLine(order);
            }

            Console.WriteLine("\nUpdate order 1 customer to 'John':");
            order1.Customer = "John";
            orderService.UpdateOrder(order1);
            Console.WriteLine(orderService.Orders.First(o => o.Id == 1));

            Console.WriteLine("\nDelete order 2:");
            orderService.DeleteOrder(2);
            Console.WriteLine("Remaining orders:");
            foreach (var order in orderService.Orders)
            {
                Console.WriteLine(order);
            }
            Console.WriteLine("\nExport orders to orders.xml:");
            orderService.Export("orders.xml");

            Console.WriteLine("\nDelete all orders:");
            foreach (var order in orderService.Orders.ToList())
            {
                orderService.DeleteOrder(order.Id);
            }
            Console.WriteLine("Remaining orders:");
            foreach (var order in orderService.Orders)
            {
                Console.WriteLine(order);
            }

            Console.WriteLine("\nImport orders from orders.xml:");
            orderService.Import("orders.xml");
            Console.WriteLine("Imported orders:");
            foreach (var order in orderService.Orders)
            {
                Console.WriteLine(order);
            }
        }
        catch (ArgumentException e)
        {
            Console.WriteLine($"Error: {e.Message}");
        }
        Console.Read();
    }
}






